
/****************************************************************************
 * 文件名称：main.c
 * 功能描述：包含System Timer(STIM)的配置函数。使用了参考手册中的“System Timer(STIM)”章节的寄存器。
 * SDK说明：使用SDK_RTM 1.0.0中的C程序文件
 * 注意事项：1，STIM模块中包含4个通道，每个通道有独立的32位计数寄存器、比较值寄存器、状态和控制寄存器、
 * 				中断使能位和标志位、独立的时钟源选择和分频，等等，等同与有4个系统定时器。
 * 			 2，4个系统定时器通道，对应同一个IRQ中断向量。
 *
 * 文件制作：智芯半导体，张允杰
 * 修改日期：2023.04.08
 * 修改记录：1，
 *
 * Copyright (C) 2020-2023 Zhixin Semiconductor Ltd. All rights reserved.
 ****************************************************************************/

// 包含序需要使用的头文件
#include "platform_cfg.h" // 包含MCU平台配置信息的头文件
#include "common_drv.h"	  // 包含SDK中常用信息的头文件

#include "sysctrl_drv.h" // 包含系统控制模块的头文件
#include "clock_drv.h"	 // 包含时钟模块的头文件
#include "gpio_drv.h"	 // 包含 GPIO 模块的头文件
#include "wdog_drv.h"	 // 包含 WDOG 模块的头文件

#include "stim_drv.h"

/* ***** 定义和声明全局变量 ******/

extern uint32_t __vector_table; // 声明中断向量表

volatile unsigned int STIM0_Int_Counter; // STIM0的中断次数计数变量
volatile unsigned int STIM1_Int_Counter; // STIM1的中断次数计数变量
volatile unsigned int STIM2_Int_Counter; // STIM2的中断次数计数变量
volatile unsigned int STIM3_Int_Counter; // STIM3的中断次数计数变量

// 定义结构体全局变量，存放 STIM 模块通道0的配置数据
const STIM_Config_t STIM0_Config =
	{
		.workMode = STIM_FREE_COUNT,			// STIM0自由加计数模式
		.compareValue = 20000,					// STIM使用20M的时钟源，STIM0定时周期为1ms
		.countResetMode = STIM_INCREASE_FROM_0, // STIM0复位，从0开始计数
		.clockSource = STIM_FUNCTION_CLOCK,		// STIM0选择STIM模块的时钟源，即函数CLK_ModuleSrc选择的时钟
		.pinSource = STIM_PIN_0,				// 选择输入信号的引脚，来自TMU。脉冲计数模式下有效
		.pinPoalrity = STIM_ACTIVE_HIGH,		// 选择输入信号 acitve 状态的极性。脉冲计数模式下有效
		.prescalerOrFilterValue = STIM_DIV_2,	// 选择输入信号的分频系数/滤波值，
		.prescalerMode = DISABLE				// 禁止分频/滤波。在自由计数模式，用作分频；在脉冲计数模式，被用作滤波
};

// 定义结构体全局变量，存放 STIM 模块通道1的配置数据
const STIM_Config_t STIM1_Config =
	{
		.workMode = STIM_FREE_COUNT,			// STIM1自由加计数模式
		.compareValue = 200000,					// STIM使用20M的时钟源，STIM1定时周期为10ms
		.countResetMode = STIM_INCREASE_FROM_0, // STIM1复位，从0开始计数
		.clockSource = STIM_FUNCTION_CLOCK,		// STIM1选择STIM模块的时钟源，即函数CLK_ModuleSrc选择的时钟
		.pinSource = STIM_PIN_0,				// 选择输入信号的引脚，来自TMU。脉冲计数模式下有效
		.pinPoalrity = STIM_ACTIVE_HIGH,		// 选择输入信号 acitve 状态的极性。脉冲计数模式下有效
		.prescalerOrFilterValue = STIM_DIV_2,	// 选择输入信号的分频系数/滤波值，
		.prescalerMode = DISABLE				// 禁止分频/滤波。在自由计数模式，用作分频；在脉冲计数模式，被用作滤波
};

// 定义结构体全局变量，存放 STIM 模块通道2的配置数据
const STIM_Config_t STIM2_Config =
	{
		.workMode = STIM_FREE_COUNT,			// STIM2自由加计数模式
		.compareValue = 2000000,				// STIM使用20M的时钟源，STIM2定时周期为100ms
		.countResetMode = STIM_INCREASE_FROM_0, // STIM2复位，从0开始计数
		.clockSource = STIM_FUNCTION_CLOCK,		// STIM2选择STIM模块的时钟源，即函数CLK_ModuleSrc选择的时钟
		.pinSource = STIM_PIN_0,				// 选择输入信号的引脚，来自TMU。脉冲计数模式下有效
		.pinPoalrity = STIM_ACTIVE_HIGH,		// 选择输入信号 acitve 状态的极性。脉冲计数模式下有效
		.prescalerOrFilterValue = STIM_DIV_2,	// 选择输入信号的分频系数/滤波值，
		.prescalerMode = DISABLE				// 禁止分频/滤波。在自由计数模式，用作分频；在脉冲计数模式，被用作滤波
};

// 定义结构体全局变量，存放 STIM 模块通道3的配置数据
const STIM_Config_t STIM3_Config =
	{
		.workMode = STIM_FREE_COUNT,			// STIM3自由加计数模式
		.compareValue = 20000000,				// STIM使用20M的时钟源，STIM3定时周期为1s
		.countResetMode = STIM_INCREASE_FROM_0, // STIM3复位，从0开始计数
		.clockSource = STIM_FUNCTION_CLOCK,		// STIM3选择STIM模块的时钟源，即函数CLK_ModuleSrc选择的时钟
		.pinSource = STIM_PIN_0,				// 选择输入信号的引脚，来自TMU。脉冲计数模式下有效
		.pinPoalrity = STIM_ACTIVE_HIGH,		// 选择输入信号 acitve 状态的极性。脉冲计数模式下有效
		.prescalerOrFilterValue = STIM_DIV_2,	// 选择输入信号的分频系数/滤波值，
		.prescalerMode = DISABLE				// 禁止分频/滤波。在自由计数模式，用作分频；在脉冲计数模式，被用作滤波
};

/* ***** 被测功能模块的配置函数 ****** */

// 声明中断函数，这些函数只在这个文件中调用
void STIM_CH0_ISR(void);
void STIM_CH1_ISR(void);
void STIM_CH2_ISR(void);
void STIM_CH3_ISR(void);

/*****************************************************************************
 * 函数:SystemTimer_Init
 * 功能:配置System Timer(STIM)模块的所有通道，System Timer(STIM)包含4个通道。
 * 参数:
 * 返回:
 * 说明:1，STIM模块中包含4个通道，每个通道有独立计数寄存器、比较值寄存器、状态和控制寄存器、
 * 				中断使能位和标志位、独立的时钟源选择和分频，等等，等同与有4个系统定时器。
 * 		2，4个系统定时器通道，对应同一个IRQ中断向量。
 ****************************************************************************/
void SystemTimer_Init(void)
{
	// 初始化STIM模块
	CLK_ModuleSrc(CLK_STIM, CLK_SRC_HSOSC); // 设置STIM模块的时钟源
	CLK_SetClkDivider(CLK_STIM, CLK_DIV_2); // 设置STIM时钟的分频器。模块的时钟不能高于CPU的总线时钟
	SYSCTRL_ResetModule(SYSCTRL_STIM);		// 在系统控制模块中，复位STIM模块
	SYSCTRL_EnableModule(SYSCTRL_STIM);		// 使能STIM模块

	// 初始化STIM模块的4个通道
	STIM_Init(STIM_0, &STIM0_Config); // 初始化STIM模块通道0
	STIM_Init(STIM_1, &STIM1_Config); // 初始化STIM模块通道1
	STIM_Init(STIM_2, &STIM2_Config); // 初始化STIM模块通道2
	STIM_Init(STIM_3, &STIM3_Config); // 初始化STIM模块通道3

	// 初始化STIM中断
	STIM_IntCmd(STIM_0, ENABLE); // 禁止STIM模块通道0的中断
	STIM_IntCmd(STIM_1, ENABLE); // 禁止STIM模块通道1的中断
	STIM_IntCmd(STIM_2, ENABLE); // 禁止STIM模块通道2的中断
	STIM_IntCmd(STIM_3, ENABLE); // 禁止STIM模块通道3的中断
	STIM_ClearInt(STIM_0);		 // 清除STIM模块通道0的中断标志
	STIM_ClearInt(STIM_1);		 // 清除STIM模块通道1的中断标志
	STIM_ClearInt(STIM_2);		 // 清除STIM模块通道2的中断标志
	STIM_ClearInt(STIM_3);		 // 清除STIM模块通道3的中断标志

	STIM_InstallCallBackFunc(STIM_0, STIM_INT, STIM_CH0_ISR); // 加载STIM模块通道0的中断处理函数
	STIM_IntCmd(STIM_0, ENABLE);							  // 使能STIM模块通道0的中断

	// STIM_InstallCallBackFunc(STIM_1, STIM_INT, STIM_CH1_ISR);	//加载STIM模块通道1的中断处理函数
	// STIM_IntCmd(STIM_1, ENABLE);				//使能STIM模块通道1的中断

	// STIM_InstallCallBackFunc(STIM_2, STIM_INT, STIM_CH2_ISR);	//加载STIM模块通道2的中断处理函数
	// STIM_IntCmd(STIM_2, ENABLE);				//使能STIM模块通道2的中断

	STIM_InstallCallBackFunc(STIM_3, STIM_INT, STIM_CH3_ISR); // 加载STIM模块通道3的中断处理函数
	STIM_IntCmd(STIM_3, ENABLE);							  // 使能STIM模块通道3的中断

	NVIC_SetPriority(STIM_IRQn, 0x1); // 设置 STIM_IRQn 的中断优先级。(高)0--15(低)
	NVIC_EnableIRQ(STIM_IRQn);		  // 使能 STIM_IRQn 中断

	// 初始化全局变量
	STIM0_Int_Counter = 0; // STIM0的中断次数计数变量
	STIM1_Int_Counter = 0; // STIM1的中断次数计数变量
	STIM2_Int_Counter = 0; // STIM2的中断次数计数变量
	STIM3_Int_Counter = 0; // STIM3的中断次数计数变量

	// 启动模块，开始运行
	STIM_Enable(STIM_0); // 使能STIM模块通道0，通道0开始运行
	// STIM_Enable(STIM_1);						//使能STIM模块通道1，通道1开始运行
	// STIM_Enable(STIM_2);						//使能STIM模块通道2，通道2开始运行
	STIM_Enable(STIM_3); // 使能STIM模块通道3，通道3开始运行
}

/*****************************************************************************
 * 函数:STIM_CH0_ISR
 * 功能:System Timer(STIM)模块通道0的中断处理函数，1ms定时中断
 * 参数:
 * 返回:
 * 说明:
 ****************************************************************************/
void STIM_CH0_ISR(void)
{
	STIM_ClearInt(STIM_0); // 清除STIM模块通道0的中断标志

	// GPIO_TogglePinOutput(PORT_B, GPIO_4);	//反转GPIO的电平，控制蓝色LED

	STIM0_Int_Counter++; // STIM0的中断次数计数变量

	// TDG_SoftwareTrig(TDG0_ID);	//Trigger TDG，用于产生6个ADC的触发信号。
}

/*****************************************************************************
 * 函数:STIM_CH1_ISR
 * 功能:System Timer(STIM)模块通道1的中断处理函数
 * 参数:
 * 返回:
 * 说明:
 ****************************************************************************/
void STIM_CH1_ISR(void)
{
	STIM_ClearInt(STIM_1); // 清除STIM模块通道1的中断标志

	// GPIO_TogglePinOutput(PORT_B, GPIO_5);	//反转GPIO的电平，控制红色LED

	STIM1_Int_Counter++; // STIM1的中断次数计数变量
}

/*****************************************************************************
 * 函数:STIM_CH2_ISR
 * 功能:System Timer(STIM)模块通道2的中断处理函数
 * 参数:
 * 返回:
 * 说明:
 ****************************************************************************/
void STIM_CH2_ISR(void)
{
	STIM_ClearInt(STIM_2); // 清除STIM模块通道2的中断标志

	// GPIO_TogglePinOutput(PORT_D, GPIO_16);	//反转GPIO的电平，控制绿色LED

	STIM2_Int_Counter++; // STIM2的中断次数计数变量
}

/*****************************************************************************
 * 函数:STIM_CH3_ISR
 * 功能:System Timer(STIM)模块通道3的中断处理函数
 * 参数:
 * 返回:
 * 说明:
 ****************************************************************************/
void STIM_CH3_ISR(void)
{
	STIM_ClearInt(STIM_3); // 清除STIM模块通道3的中断标志

	GPIO_TogglePinOutput(PORT_B, GPIO_4);  // 反转GPIO的电平，控制蓝色LED
	GPIO_TogglePinOutput(PORT_B, GPIO_5);  // 反转GPIO的电平，控制红色LED
	GPIO_TogglePinOutput(PORT_D, GPIO_16); // 反转GPIO的电平，控制绿色LED

	STIM3_Int_Counter++; // STIM3的中断次数计数变量
}

/* ***** 系统基础模块的配置函数 ****** */

/* PLL 的设置说明。参考手册中“SPLL frequency”
 * 1，Fpll = ((RefClk÷PreDiv)×Multi×PreScaler)÷PostDiv；
 * 2，PLL 的时钟源分频之后的时钟频率必须在范围(4-16MHz)内；
 * 3，PLL 倍频之后的频率必须在范围(0.8-1.2GHz)内。
 */

// 定义PLL的初始化参数，以FIRC作为PLL的时钟源，PLL输出160MHz 的时钟
//((64÷4)×30×2)÷6 = 160；
const CLK_PLLConfig_t CLK_PLL_Config =
	{
		.pllPreDivider = PLL_PRE_DIV_VALUE_4,	// PLL时钟源的分频系数
		.pllPostDivider = PLL_POST_DIV_VALUE_6, // PLL时钟输出前的分频系数
		.pllMultiplier = 30,					// PLL的倍频系数，取值范围是 8--255
		.pllRefClock = PLL_FIRC_CLK,			// 选择FIRC作为PLL的时钟源
		.pllPreScaler = PLL_SCALER_VALUE_2,		// PLL的预倍频系数
};

/*
//定义PLL的初始化参数，以FIRC作为PLL的时钟源，PLL输出120MHz的时钟
//((64÷4)×30×2)÷8 = 120；
const CLK_PLLConfig_t CLK_PLL_Config =
{
	.pllPreDivider = PLL_PRE_DIV_VALUE_4,	//PLL时钟源的分频系数
	.pllPostDivider = PLL_POST_DIV_VALUE_8,	//PLL时钟输出前的分频系数
	.pllMultiplier = 30,					//PLL的倍频系数，取值范围是 8--255
	.pllRefClock = PLL_FIRC_CLK,			//选择FIRC作为PLL的时钟源
	.pllPreScaler = PLL_SCALER_VALUE_2,		//PLL的预倍频系数
};
*/

static uint32_t CLK_PLL_Int_Cnt; // PLL 中断次数计数器

// 声明中断函数，这些函数只在这个文件中调用
void CLOCK_PLLLOC_ISR(void); // 声明PLL失锁中断执行函数

/*****************************************************************************
 * 函数:CLOCK_Init
 * 功能:配置时钟模块(SCC)。
 * 参数:
 * 返回:
 * 说明:1，Fpll = ((RefClk÷PreDiv)×Multi×PreScaler)÷PostDiv；PLL 的时钟源分频之后的
 * 			时钟频率必须在范围(4-16MHz)内；倍频之后的频率必须在范围(0.8-1.2GHz)内。
 * 		2，读取FLASH时，使用的是内核时钟。FLASH控制器的时钟典型值是8Mhz。
 *		3，系统时钟的说明，参考“Peripheral clock summary”。
 *		4，根据多次 EMC 测试中出现的时钟问题，要求：PLL的时钟源选择内部的 FIRC，确保内核和总线时钟的稳定，PLL的
 *			输出尽量设置到最大；对时钟精度要求高的模块，时钟源选择外部晶振，其他的模块，时钟源选择内部的 FIRC。
 *		5，当外部晶振的频率大于等于24MHz时，晶振的模式推荐选择高频模式。小于等于20MHz时，晶振的模式推荐选择低频模式。
 ****************************************************************************/
void CLOCK_Init(void)
{
	uint32_t clk_wait_cnt;

	CLK_PLLDisable(); // 禁止 PLL

	// 关闭 CLOCK 的中断，清除中断标志位
	CLK_HSOSCMonitorDisable();		// 禁止对外部晶振的监控，失速不产生中断
	CLK_FIRCMonitorDisable();		// 禁止对内部FIRC的监控，失速不产生中断
	CLK_PLLMonitorDisable();		// 禁止对PLL的监控，失锁不产生中断
	CLK_IntClear(CLK_INT_HSOSCLOC); // 清除外部晶振的中断标志
	CLK_IntClear(CLK_INT_FIRCLOC);	// 清除内部FIRC的中断标志
	CLK_IntClear(CLK_INT_PLLLOC);	// 清除PLL的中断标志

	// 初始化根时钟源
	CLK_LPO32KEnable();													 // 使能内部32K的时钟源
	CLK_OSC32KDisable();												 // 禁止外部32K晶振
	CLK_FIRCEnable(ENABLE);												 // 使能FIRC，允许在STOP模式下运行
	(void)CLK_HSOSCEnable(CLK_OSC_FREQ_MODE_HIGH, ENABLE, CLK_OSC_XTAL); // 高频模式(>=24M)，STOP下运行，外部晶振模式
	clk_wait_cnt = 0;
	while (CLK_WaitClkReady(CLK_SRC_HSOSC) != SUCC)
	{
		clk_wait_cnt++;
		if (clk_wait_cnt > 5)
			break; // 跳出 while 循环
	}

	// 初始化 PLL模块
	CLK_PLLConfig(&CLK_PLL_Config); // 使用CLK_PLL_Config 中的数据初始化PLLOK
	CLK_PLLEnable(ENABLE);

	// 初始化系统时钟的时钟源、分频系数、PLL监控中断
	if (CLK_WaitClkReady(CLK_SRC_PLL) == SUCC) // PLL已经稳定。
	{
		CLK_SysClkSrc(CLK_SYS_PLL);				 // 选择 PLL 输出的时钟作为系统时钟的时钟源
		CLK_SetClkDivider(CLK_CORE, CLK_DIV_1);	 // 设置内核时钟的分频系数
		CLK_SetClkDivider(CLK_BUS, CLK_DIV_2);	 // 设置总线时钟的分频系数。考虑功能可靠性，总线时钟设为内核时钟的1/2。
		CLK_SetClkDivider(CLK_SLOW, CLK_DIV_16); // 设置Slow_Clock的分频系数

		CLK_IntClear(CLK_INT_PLLLOC);								// 清除PLL的中断标志
		CLK_InstallCallBackFunc(CLK_INT_PLLLOC, &CLOCK_PLLLOC_ISR); // 加载中断处理函数
		CLK_PLLMonitorEnable(CLK_MON_INT);							// 使能对PLL的监控，PLL时钟偏离，产生中断
	}
	else // PLL没有稳定。
	{
		CLK_SysClkSrc(CLK_SYS_FIRC);			// 选择 FIRC 作为系统时钟的时钟源
		CLK_SetClkDivider(CLK_CORE, CLK_DIV_1); // 设置内核时钟的分频系数
		CLK_SetClkDivider(CLK_BUS, CLK_DIV_2);	// 设置总线时钟的分频系数。考虑功能可靠性，总线时钟设为内核时钟的1/2。
		CLK_SetClkDivider(CLK_SLOW, CLK_DIV_8); // 设置Slow_Clock的分频系数

		CLK_PLLDisable(); // 禁止 PLL
		// CLK_PLLMonitorDisable();		//禁止对PLL的监控，失锁不产生中断。这一句不能使用
		CLK_IntClear(CLK_INT_PLLLOC); // 清除PLL的中断标志
	}

	// 初始化时钟输出功能
	CLK_ClkOutDisable(); // 禁止时钟输出

	// 初始化CLOCK中断
	// CLK_InstallCallBackFunc(CLK_INT_HSOSCLOC, &CLOCK__OSCLOC_ISR);//加载中断处理函数
	// CLK_HSOSCMonitorEnable(CLK_MON_INT);	//使能对外部晶振的监控，晶振时钟偏离，产生中断

	NVIC_SetPriority(SCC_IRQn, 0x0); // 设置 SCC_IRQn 的中断优先级。(高)0--15(低)
	NVIC_EnableIRQ(SCC_IRQn);		 // 使能 SCC_IRQn 中断
	// NVIC_DisableIRQ(SCC_IRQn);		//禁止 SCC_IRQn 中断

	// 初始化变量
	CLK_PLL_Int_Cnt = 0; // PLL 中断次数计数器

	// 启动模块，模块开始运行
}

/*****************************************************************************
 * 函数:CLOCK_PLLLOC_ISR
 * 功能:PLL失锁中断执行函数。
 * 参数:
 * 返回:
 * 说明:1，
 ****************************************************************************/
void CLOCK_PLLLOC_ISR(void)
{
	CLK_SysClkSrc(CLK_SYS_FIRC); // 选择 FIRC 作为系统时钟的时钟源

	CLK_PLLMonitorDisable();	  // 禁止对PLL的监控，失锁不产生中断
	CLK_IntClear(CLK_INT_PLLLOC); // 清除PLL的中断标志

	// 重新初始化 PLL模块
	CLK_PLLConfig(&CLK_PLL_Config); // 使用CLK_PLL_Config 中的数据初始化PLLOK
	CLK_PLLEnable(ENABLE);

	// 初始化系统时钟的时钟源、分频系数、PLL监控中断
	if (CLK_WaitClkReady(CLK_SRC_PLL) == SUCC) // PLL已经稳定。
	{
		CLK_SysClkSrc(CLK_SYS_PLL);				 // 选择 PLL 输出的时钟作为系统时钟的时钟源
		CLK_SetClkDivider(CLK_CORE, CLK_DIV_1);	 // 设置内核时钟的分频系数
		CLK_SetClkDivider(CLK_BUS, CLK_DIV_2);	 // 设置总线时钟的分频系数。考虑功能可靠性，总线时钟设为内核时钟的1/2。
		CLK_SetClkDivider(CLK_SLOW, CLK_DIV_16); // 设置Slow_Clock的分频系数

		CLK_IntClear(CLK_INT_PLLLOC);								// 清除PLL的中断标志
		CLK_InstallCallBackFunc(CLK_INT_PLLLOC, &CLOCK_PLLLOC_ISR); // 加载中断处理函数
		CLK_PLLMonitorEnable(CLK_MON_INT);							// 使能对PLL的监控，PLL时钟偏离，产生中断

		return;
	}
	else // PLL没有稳定。
	{
		CLK_SysClkSrc(CLK_SYS_FIRC);			// 选择 FIRC 作为系统时钟的时钟源
		CLK_SetClkDivider(CLK_CORE, CLK_DIV_1); // 设置内核时钟的分频系数
		CLK_SetClkDivider(CLK_BUS, CLK_DIV_2);	// 设置总线时钟的分频系数。考虑功能可靠性，总线时钟设为内核时钟的1/2。
		CLK_SetClkDivider(CLK_SLOW, CLK_DIV_8); // 设置Slow_Clock的分频系数

		// CLK_PLLDisable();				//禁止 PLL
		// CLK_PLLMonitorDisable();		//禁止对PLL的监控，失锁不产生中断
		// CLK_IntClear(CLK_INT_PLLLOC);	//清除PLL的中断标志

		return;
	}

	/**/
	// 避免频繁进入 PLL 中断的设置
	CLK_PLL_Int_Cnt++; // PLL 中断次数计数器
	if (CLK_PLL_Int_Cnt > 50)
	{
		CLK_PLL_Int_Cnt = 55; // PLL 中断次数计数器

		// CLK_SysClkSrc(CLK_SYS_FIRC);			//选择 FIRC 作为系统时钟的时钟源
		CLK_SetClkDivider(CLK_CORE, CLK_DIV_1); // 设置内核时钟的分频系数
		CLK_SetClkDivider(CLK_BUS, CLK_DIV_2);	// 设置总线时钟的分频系数。考虑功能可靠性，总线时钟设为内核时钟的1/2。
		CLK_SetClkDivider(CLK_SLOW, CLK_DIV_8); // 设置Slow_Clock的分频系数

		CLK_PLLDisable();			  // 禁止 PLL
		CLK_PLLMonitorDisable();	  // 禁止对PLL的监控，失锁不产生中断
		CLK_IntClear(CLK_INT_PLLLOC); // 清除PLL的中断标志

		return;
	}
}

/*****************************************************************************
 * 函数:PORT_Init
 * 功能:配置所有使用到的PORT模块。具体每个IO的初始化，在应用该IO的模块中处理。
 * 参数:
 * 返回:
 * 说明:1，MCU有个PORT模块，包括 PORTA、PORTB、PORTC、PORTD、PORTE模块；
 * 		2，具体每个IO的初始化，在应用该IO的模块中处理。比如，用作GPIO功能的IO，
 * 			在“BSP_GPIO.c”中完成初始化；用做附件功能的端口的初始化，在对应的功
 * 			能模块中完成；避免重复初始化端口，对软件系统产生干扰和风险。
 ****************************************************************************/
void PORT_Init(void)
{
	/* ***** 初始化PORT模块 ***** */
	CLK_ModuleSrc(CLK_PORTA, CLK_SRC_FIRC);	 // 选择PORTA模块的时钟源
	CLK_SetClkDivider(CLK_PORTA, CLK_DIV_4); // 设置PORTA时钟的分频器。模块的时钟不能高于CPU的总线时钟
	SYSCTRL_ResetModule(SYSCTRL_PORTA);		 // 在系统控制模块中，复位PORTA模块
	SYSCTRL_EnableModule(SYSCTRL_PORTA);	 // 在PARCC中，使能PORTA模块

	CLK_ModuleSrc(CLK_PORTB, CLK_SRC_FIRC);	 // 选择PORTB模块的时钟源
	CLK_SetClkDivider(CLK_PORTB, CLK_DIV_4); // 设置PORTB时钟的分频器。模块的时钟不能高于CPU的总线时钟
	SYSCTRL_ResetModule(SYSCTRL_PORTB);		 // 在系统控制模块中，复位PORTB模块
	SYSCTRL_EnableModule(SYSCTRL_PORTB);	 // 在PARCC中，使能PORTB模块

	CLK_ModuleSrc(CLK_PORTC, CLK_SRC_FIRC);	 // 选择PORTC模块的时钟源
	CLK_SetClkDivider(CLK_PORTC, CLK_DIV_4); // 设置PORTC时钟的分频器。模块的时钟不能高于CPU的总线时钟
	SYSCTRL_ResetModule(SYSCTRL_PORTC);		 // 在系统控制模块中，复位PORTC模块
	SYSCTRL_EnableModule(SYSCTRL_PORTC);	 // 在PARCC中，使能PORTC模块

	CLK_ModuleSrc(CLK_PORTD, CLK_SRC_FIRC);	 // 选择PORTD模块的时钟源
	CLK_SetClkDivider(CLK_PORTD, CLK_DIV_4); // 设置PORTD时钟的分频器。模块的时钟不能高于CPU的总线时钟
	SYSCTRL_ResetModule(SYSCTRL_PORTD);		 // 在系统控制模块中，复位PORTD模块
	SYSCTRL_EnableModule(SYSCTRL_PORTD);	 // 在PARCC中，使能PORTD模块

	CLK_ModuleSrc(CLK_PORTE, CLK_SRC_FIRC);	 // 选择PORTE模块的时钟源
	CLK_SetClkDivider(CLK_PORTE, CLK_DIV_4); // 设置PORTE时钟的分频器。模块的时钟不能高于CPU的总线时钟
	SYSCTRL_ResetModule(SYSCTRL_PORTE);		 // 在系统控制模块中，复位PORTE模块
	SYSCTRL_EnableModule(SYSCTRL_PORTE);	 // 在PARCC中，使能PORTE模块

	// 初始化PORT中断
	PORT_ClearPinsInt(PORT_A, 0xFFFFFFFF); // 清除PORTA所有的中断标志
	PORT_ClearPinsInt(PORT_B, 0xFFFFFFFF); // 清除PORTB所有的中断标志
	PORT_ClearPinsInt(PORT_C, 0xFFFFFFFF); // 清除PORTC所有的中断标志
	PORT_ClearPinsInt(PORT_D, 0xFFFFFFFF); // 清除PORTD所有的中断标志
	PORT_ClearPinsInt(PORT_E, 0xFFFFFFFF); // 清除PORTE所有的中断标志

	// PORT_InstallCallBackFunc(&PORT_ISR);	//加载中断处理函数

	NVIC_SetPriority(PORTA_IRQn, 0x3); // 设置 PORTA_IRQn 的中断优先级。(高)0--15(低)
	NVIC_DisableIRQ(PORTA_IRQn);	   // 禁止 PORTA_IRQn 中断

	NVIC_SetPriority(PORTB_IRQn, 0x3); // 设置 PORTA_IRQn 的中断优先级。(高)0--15(低)
	NVIC_DisableIRQ(PORTB_IRQn);	   // 禁止 PORTA_IRQn 中断

	NVIC_SetPriority(PORTC_IRQn, 0x3); // 设置 PORTA_IRQn 的中断优先级。(高)0--15(低)
	NVIC_DisableIRQ(PORTC_IRQn);	   // 禁止 PORTA_IRQn 中断

	NVIC_SetPriority(PORTD_IRQn, 0x3); // 设置 PORTA_IRQn 的中断优先级。(高)0--15(低)
	NVIC_DisableIRQ(PORTD_IRQn);	   // 禁止 PORTA_IRQn 中断

	NVIC_SetPriority(PORTE_IRQn, 0x3); // 设置 PORTA_IRQn 的中断优先级。(高)0--15(低)
	NVIC_DisableIRQ(PORTE_IRQn);	   // 禁止 PORTA_IRQn 中断

	// 启动模块，模块开始运行
}

/*****************************************************************************
 * 函数:GPIO_Init
 * 功能:配置GPIO模块，初始化GPIO功能的端口。不包括用做附加功能的端口。
 * 参数:
 * 返回:
 * 说明:1，用做附件功能的端口的初始化，在对应的功能模块中完成，避免重复初始化端口，对软件
 * 			系统产生干扰和风险。
 * 		2，
 ****************************************************************************/
void GPIO_Init(void)
{
	/* ***** 初始化GPIO模块 ***** */
	SYSCTRL_ResetModule(SYSCTRL_GPIO);	// 在系统控制模块中，复位GPIO模块
	SYSCTRL_EnableModule(SYSCTRL_GPIO); // 在PARCC中，使能GPIO模块。在PARCC中，GPIO有一个单独的控制寄存器

	/* ***** 初始化用作GPIO功能的端口 ***** */
	PORT_PinmuxConfig(PORT_B, GPIO_4, PTB4_GPIO); // 配置 PTB4 端口为GPIO功能。控制蓝色LED
	GPIO_SetPinDir(PORT_B, GPIO_4, GPIO_OUTPUT);  // 设置 PTB4 端口的方向为GPIO输出
	GPIO_ClearPinOutput(PORT_B, GPIO_4);		  // 设置 PTB4 输出 0

	PORT_PinmuxConfig(PORT_B, GPIO_5, PTB5_GPIO); // 配置 PTB5 端口为GPIO功能。控制红色LED
	GPIO_SetPinDir(PORT_B, GPIO_5, GPIO_OUTPUT);  // 设置 PTB5 端口的方向为GPIO输出
	GPIO_ClearPinOutput(PORT_B, GPIO_5);		  // 设置 PTB5 输出 0

	PORT_PinmuxConfig(PORT_D, GPIO_16, PTD16_GPIO); // 配置 PTD16 端口为GPIO功能。控制绿色LED
	GPIO_SetPinDir(PORT_D, GPIO_16, GPIO_OUTPUT);	// 设置 PTD16 端口的方向为GPIO输出
	GPIO_ClearPinOutput(PORT_D, GPIO_16);			// 设置 PTD16 输出 0
}

/*****************************************************************************
 * 函数:System_Init
 * 功能:初始化系统，初始所有使用的MCU集成外设。
 * 参数:
 * 返回:
 * 说明:
 ****************************************************************************/
void System_Init(void)
{
	// ResultStatus_t ret;

	SCB->VTOR = ((uint32_t)&__vector_table) & 0xFFFFFF00U; // 清除内核寄存器VTOR的后8位
	CORE_DSB();											   // 数据同步，在这个指令之前，完成所有的就存储器处理工作。

	CLOCK_Init(); // 初始化系统的时钟源
	PORT_Init();  // 初始化所有使用到的PORT模块
	GPIO_Init();  // 初始化GPIO模块

	SystemTimer_Init(); // 初始化STIM模块

	// 这两句仅在测试时使用
	SYSCTRL_EnableModule(SYSCTRL_WDOG); // 使能看门狗模块
	WDOG_Disable();						// 禁止看门狗，同时使能了 IQR 全局中断

	CORE_ENABLE_IRQ(); // 使能 I+RQ 全局中断
}

/*****************************************************************************
 * 函数: main
 * 功能: 系统主函数
 * 参数:
 * 返回:
 * 说明:
 ****************************************************************************/
int main(void)
{
	System_Init(); // 初始化系统的硬件和全局变量

	// GPIO和STIM中断测试
	while (1)
	{
		if(STIM0_Int_Counter > 100 )
		{
			STIM0_Int_Counter = 0;
			GPIO_TogglePinOutput(PORT_B, GPIO_4);	//反转GPIO的电平，控制蓝色LED
		}

		if(STIM1_Int_Counter > 100 )
		{
			STIM1_Int_Counter = 0;
			//GPIO_TogglePinOutput(PORT_B, GPIO_5);	//反转GPIO的电平，控制红色LED
		}

		if(STIM2_Int_Counter > 100 )
		{
			STIM2_Int_Counter = 0;
			//GPIO_TogglePinOutput(PORT_D, GPIO_16);	//反转GPIO的电平，控制绿色LED
		}
		
	}
}
